
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#include<time.h>
#include<unistd.h>
#include "els.h"
#include "els_c_api.h"
void els_core_inc(void);
void els_core_eval(void);
void els_core_end(void){}

#ifdef PLATLINUX
#include<dlfcn.h>
#endif
#ifdef PLATWINDOWS
#include<windows.h>
#endif
void els_FFI_C(void){
    #ifdef PLATLINUX
    char incdir[512]="/els/lib/";
    typedef LNI_return (*ELS_C_FFI)(LNI_argv a);
    if(els_isstr(els_getstack(1))&&els_isstr(els_getstack(2))){
        strcat(incdir,els_getstr(els_getstack(1)));
        char *libname = els_getstr(els_getstack(1));
        char *funcname = els_getstr(els_getstack(2));
        void* _ptr_dll = dlopen(libname,RTLD_NOW);
        if (!_ptr_dll) _ptr_dll = dlopen(incdir,RTLD_NOW);
        if(!_ptr_dll)   els_error("无法加载C库!"),exit(-1);
        ELS_C_FFI c_api;
        LNI_argv argv;
        int i = 0;
        while(i<13){
            els_Typesystem_Object o = els_getstack(++i);
            argv.type[i] = els_type(o);
            argv.str[i] = els_getstr(o);
            argv.num[i] = els_getnum(o);
        }
        c_api = (ELS_C_FFI)dlsym(_ptr_dll,funcname);
        if(c_api==NULL) els_error("找不到C函数!"),exit(-1);
        LNI_return rt =  c_api(argv); 
        if(rt.type==ELS_TYPE_NUMBER) {els_pushnum(rt.num);}
        if(rt.type==ELS_TYPE_STRING) {els_pushstr(rt.str);}
    }
    return;
    #endif
    #ifdef PLATWINDOWS
    char incdir[512];sprintf(incdir,"%s%s",getenv("LOSU"),"/lib/");
    typedef LNI_return (*ELS_C_FFI)(LNI_argv a);
    if(els_isstr(els_getstack(1))&&els_isstr(els_getstack(2))){
        strcat(incdir,els_getstr(els_getstack(1)));
        char *libname = els_getstr(els_getstack(1));
        char *funcname = els_getstr(els_getstack(2));
        HMODULE _ptr_dll = LoadLibrary(libname);
        if (!_ptr_dll) _ptr_dll =  LoadLibrary(libname);
        if(!_ptr_dll)   els_error("无法加载C库");
        ELS_C_FFI c_api;
        LNI_argv argv;
        int i = 0;
        while(i<13){
            els_Typesystem_Object o = els_getstack(++i);
            argv.type[i] = els_type(o);
            argv.str[i] = els_getstr(o);
            argv.num[i] = els_getnum(o);
        }


        c_api = (ELS_C_FFI)GetProcAddress(_ptr_dll,funcname);
        if(c_api==NULL) els_error("找不到C函数!");
        LNI_return rt =  c_api(argv); 
        if(rt.type==ELS_TYPE_NUMBER) els_pushnum(rt.num);
        if(rt.type==ELS_TYPE_STRING) els_pushstr(rt.str);
    }
    return;
    #endif
}
void els_load_lib(){
    #ifdef LANGCN
    els_register("库", els_FFI_C);
    els_register("引",els_core_inc);
    els_register("释",els_core_eval);
    els_register("尾",els_core_end);
    #endif
    #ifdef LANGENG
    els_register("call", els_FFI_C);
    els_register("import",els_core_inc);
    els_register("eval",els_core_eval);
    els_register("end",els_core_end);
    #endif
}
void els_core_inc(void){
    #ifdef PLATLINUX
    char incdir[512];
    if(els_getstack(1)==ELS_NO_OBJECT) els_error("方法 引 缺少参数");
    sprintf(incdir,"%s%s%s","./",els_getstr(els_getstack(1)),".els");
    FILE *fi = fopen(incdir,"r");
    if(fi>0){
        fclose(fi);
        els_dofile(incdir);
    }else{
        sprintf(incdir,"%s%s%s","/els/inc/",els_getstr(els_getstack(1)),".els");
        els_dofile(incdir);
        els_pushnull(); 
    }

    #endif
    #ifdef PLATWINDOWS
    char incdir[512];
    sprintf(incdir,"%s%s%s","./",els_getstr(els_getstack(1)),".els");
    if(els_getstack(1)==ELS_NO_OBJECT) els_error("方法 引 缺少参数");
    FILE *fi = fopen(incdir,"r");
    if(fi>0){
        fclose(fi);
        els_dofile(incdir);
    }else{
        sprintf(incdir,"%s%s%s",getenv("LOSU"),els_getstr(els_getstack(1)),".els");
        els_dofile(incdir);
        els_pushnull();
    }

    #endif

}
void els_core_eval(void){
    if(els_type(els_getstack(1))==ELS_TYPE_NULL) return;
    els_dostring(els_getstr(els_getstack(1)));

}



